<script setup>

import Draggable from "vuedraggable";
import {computed, provide, ref, toRefs, watch} from "vue";
import config from "@/utils/config";

const props = defineProps({
  modelValue: {
    type: [String, Array, Object],
    default: () => []
  },
  // 文件类型
  type: {
    type: Number,
    default: 1
  },
  // 选择器尺寸
  size: {
    type: String,
    default: '100px'
  },
  // 选择器尺寸-宽度（不传则是使用size
  width: {
    type: String,
    default: ''
  },
  // 选择器尺寸-高度（不传则是使用size
  height: {
    type: String,
    default: ''
  },
  // 选择数量限制
  limit: {
    type: Number,
    default: 1
  },
  // 禁用选择
  disabled: {
    type: Boolean,
    default: false
  },
  // 隐藏上传框*(目前在富文本中使用到)
  hiddenUpload: {
    type: Boolean,
    default: false
  },
  uploadClass: {
    type: String,
    default: ''
  },
  //选择的url排出域名
  excludeDomain: {
    type: Boolean,
    default: false
  }
})

const emit = defineEmits(['change', 'update:modelValue'])
const modalRef = ref();
const filePickerRef = ref();
const previewUrl = ref([]);
const fileList = ref([])
const showPreview = ref(false)
const showVideoPreview = ref(false)
const videoPreviewUrl = ref('')
const isAdd = ref(true)
const currentIndex = ref(-1)
const imageRef = ref()
const videoRef = ref()
const {disabled, limit, modelValue} = toRefs(props)

const tipsText = computed(() => {
  switch (props.type) {
    case 1:
      return '请上传图片'
    case 2:
      return '请上传视频'
    case 3:
      return '请上传文件'
  }
})
const showUpload = computed(() => {
  return props.limit - fileList.value.length > 0
})
const fileLimit = computed(() => {
  if (!isAdd.value) {
    return 1
  }
  if (limit.value === -1) return null
  return limit.value - fileList.value.length
})

const handleSubmit = () => {
  if (filePickerRef.value) {
    if (!isAdd.value) {
      if (filePickerRef.value.selectedFiles && filePickerRef.value.selectedFiles.length > 0) {
        fileList.value.splice(currentIndex.value, 1, filePickerRef.value.selectedFiles.shift())
      }
    } else {
      if (filePickerRef.value.selectedFiles && filePickerRef.value.selectedFiles.length > 0) {
        fileList.value = [...fileList.value, ...filePickerRef.value.selectedFiles];
      }
    }
    modalRef.value?.handleClose();
    handleChange()
  }
}

const openDialog = (index, type) => {
  if (disabled.value) return
  if (index >= 0) {
    isAdd.value = false
    currentIndex.value = index
  } else {
    isAdd.value = true
  }
  modalRef.value?.handleOpen()
}

const handleChange = () => {
  const valueImg = limit.value !== 1 ? fileList.value : fileList.value[0] || ''
  emit('update:modelValue', valueImg)
  emit('change', valueImg)
}

const deleteImg = (index, type) => {
  fileList.value.splice(index, 1)
  handleChange()
}

const handlePreview = (value, type) => {
  if (type === 1) {
    showPreview.value = true
    previewUrl.value = [`${config.imgDomain}${value?.uri}`]
  }
}

watch(modelValue, (val) => {
  fileList.value = Array.isArray(val) ? val : val === '' ? [] : [val]
}, {
  immediate: true
})

provide('limit', props.limit)
provide('hiddenUpload', props.hiddenUpload)

</script>

<template>
  <div class="picker-select">
    <div class="clearfix">
      <draggable v-model="fileList" :animation="300" item-key="id">
        <template #item="{ element: item, index }">
          <div
              class="picker-preview"
              :class="{
              'is-disabled': disabled,
              'is-one': limit === 1
            }"
              @click="type === 1 ? handlePreview(item,type) : null"
          >
            <del-wrap @close="deleteImg(index,type)">
              <el-image ref="imageRef" :style="{width:width||size,height:height||size}" v-if="type === 1"
                        :src="config.imgDomain+item.uri" fit="contain" :preview-src-list="previewUrl"/>
              <video-preview ref="videoRef" v-if="type === 2" :src="config.imgDomain+item.uri" :width="width||size"
                             :height="width||size"/>
              <img v-if="type === 3" src="@/assets/images/file_thumb.png" :width="width||size"
                   :height="width||size"/>
            </del-wrap>
            <div class="operation-btns text-xs text-center">
              <span @click.stop="openDialog(index,type)">修改</span>
              <span v-if="type === 1" class="m-1.5">|</span>
              <span v-if="type === 1" @click.stop="handlePreview(item,type)">查看</span>
            </div>
          </div>
        </template>
      </draggable>
      <div
          class="picker-upload"
          @click="openDialog(-1,type)"
          v-show="showUpload"
          :class="{
            'is-disabled':disabled,
            'is-one':limit===1,
            [uploadClass]:true
          }">
        <div
            class="upload-btn"
            :style="{
                width:width||size,
                height:height||size
              }">
          <icon size="25" icon="ep:plus" color="gray"/>
          <span>添加</span>
        </div>
      </div>
    </div>
    <dialog-form ref="modalRef" :modal-title="`选择${tipsText}`" modal-width="1300px" @submit="handleSubmit">
      <files style="height: 600px" ref="filePickerRef" :select-limit="fileLimit" :type="type" mode="picker"/>
    </dialog-form>
    <el-image-viewer
        v-if="showPreview"
        :url-list="previewUrl"
        show-progress
        @close="showPreview = false"
    />
    <el-dialog
        v-model="showVideoPreview"
        title="视频预览"
        width="800px"
        destroy-on-close
        :close-on-click-modal="false"
    >
      <video
          :src="videoPreviewUrl"
          controls
          style="width: 100%"
          autoplay
      />
    </el-dialog>
  </div>

</template>

<style scoped lang="scss">
.picker-select {
  .picker-upload,
  .picker-preview {
    position: relative;
    border-radius: 4px;
    cursor: pointer;
    margin-right: 8px;
    margin-bottom: 8px;
    box-sizing: border-box;
    float: left;

    &.is-disabled {
      cursor: not-allowed;
    }

    &.is-one {
      margin-bottom: 0;
    }

    &:hover {
      .operation-btns {
        display: block;
      }
    }

    .operation-btns {
      display: none;
      position: absolute;
      bottom: 0;
      border-radius: 4px;
      width: 100%;
      line-height: 2;
      color: #fff;
      background-color: rgba(0, 0, 0, 0.3);
    }
  }

  .picker-upload {
    :deep(.upload-btn) {
      @apply box-border rounded border-br border-dashed border flex flex-col justify-center items-center text-sm;
      background-color: transparent;
      color: gray;
    }
  }
}

.clearfix:after {
  content: "";
  display: block;
  clear: both;
  visibility: hidden;
}
</style>
